from __future__ import annotations

from dataclasses import dataclass, field
from typing import Optional
import os
import socket


@dataclass
class SMTPConfig:
    host: str
    port: int
    username: Optional[str]
    password: Optional[str]
    use_tls: bool
    from_name: str
    from_email: str

    def validate(self) -> None:
        """Validate SMTP configuration"""
        if not self.host:
            raise ValueError("SMTP_HOST cannot be empty")

        if not isinstance(self.port, int) or not (1 <= self.port <= 65535):
            raise ValueError(f"SMTP_PORT must be between 1 and 65535, got {self.port}")

        if not self.from_email or "@" not in self.from_email:
            raise ValueError(f"Invalid SMTP_FROM_EMAIL: {self.from_email}")

        # Check if host is reachable (basic check)
        try:
            socket.gethostbyname(self.host)
        except socket.gaierror:
            raise ValueError(f"Cannot resolve SMTP host: {self.host}")


def load_smtp_config() -> SMTPConfig:
    host = os.getenv("SMTP_HOST", "localhost")
    port = int(os.getenv("SMTP_PORT", "25"))
    username = os.getenv("SMTP_USERNAME")
    password = os.getenv("SMTP_PASSWORD")
    use_tls = os.getenv("SMTP_USE_TLS", "true").lower() in {"1", "true", "yes"}
    from_name = os.getenv("SMTP_FROM_NAME", "Report Mailer")
    from_email = os.getenv("SMTP_FROM_EMAIL", "noreply@example.com")
    return SMTPConfig(
        host=host,
        port=port,
        username=username,
        password=password,
        use_tls=use_tls,
        from_name=from_name,
        from_email=from_email,
    )


@dataclass
class RuntimeConfig:
    db_path: str = field(default_factory=lambda: os.getenv("MAILER_DB_PATH", "mailer.sqlite3"))
    batch_size: int = field(default_factory=lambda: int(os.getenv("MAILER_BATCH_SIZE", "100")))
    max_retries: int = field(default_factory=lambda: int(os.getenv("MAILER_MAX_RETRIES", "3")))
    rate_limit_per_sec: int = field(default_factory=lambda: int(os.getenv("MAILER_RATE_LIMIT", "10")))

    def validate(self) -> None:
        """Validate runtime configuration"""
        if self.batch_size < 1:
            raise ValueError(f"MAILER_BATCH_SIZE must be at least 1, got {self.batch_size}")

        if self.max_retries < 0:
            raise ValueError(f"MAILER_MAX_RETRIES cannot be negative, got {self.max_retries}")

        if not (1 <= self.rate_limit_per_sec <= 100):
            raise ValueError(
                f"MAILER_RATE_LIMIT must be between 1 and 100 per second, got {self.rate_limit_per_sec}"
            )


